<?php

namespace App\Console\Commands;

use App\Services\DreamBoxService;
use Exception;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Cache;
class OverTimeOrder extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'order.overtime_clear';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'clear overtime orders';

    protected $overtime = 60*60*12; // 12小时自动取消
    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        // 查询所有待支付订单中
        $wait_pay =DB::table("order")
            ->where("status",1)
            ->orWhere('pay_again',1)
            ->take(30)
            ->get();
        if(!empty($wait_pay)){
            foreach($wait_pay as $order){
                if($order->status == 1 || $order->status == 7){
                    if(strtotime($order->created_at) + $this->overtime <= time()){
                        echo $order->id;
                        $this->cancel($order);
                    }
                }
            }
        }else{
            Log::channel('overtime_order')->info('此次无数据执行',[]);
        }
    }

    private function cancel($order){
        // 事务开启
        try {
            //锁定当前订单，避免前台用户自动操作过期
            $lock_key = 'babei_order_cancel:'.$order->id;
            //设置锁
            $is_lock = $this->lock($lock_key, 120);
            if (!$is_lock) {
                throw new Exception('网络有点小卡，请稍候重试', 20000);
            }

            DB::beginTransaction();
            $order_data['status'] = 7;
            $order_data['pay_again'] = 0;
            //dd(DB::table('order')->where('id',$order->id)->update($order_data));
            if(!DB::table('order')->where('id',$order->id)->update($order_data)){
                throw new Exception("订单取消失败，请重试");
            }
            if($order->order_type != 3){
                // 移除冻结商品冻结库存
                $order_goods = DB::table('order_goods')->where('order_no','=',$order->online_order)->get();
                if(!$order_goods){
                    throw new Exception('商品信息错误，请联系客服1');
                }
                $good_data = [];
                foreach($order_goods as $og){
                    $good_info = DB::table('goods')->where('sku','=',$og->sku)->first();
                    // 售卖机不需要解冻库存
                    if($order->order_type == 1) {
                        if ($good_info->stock_freeze < $og->amount) {
                            if(intval($good_info->stock_freeze) != 0){
                                throw new Exception('商品信息错误，请联系客服2');
                            }
                        }else{
                            $good_data['stock'] = $good_info->stock + $og->amount;
                            $good_data['stock_freeze'] = $good_info->stock_freeze - $og->amount;
                            if (!DB::table('goods')->where('id', $good_info->id)->update($good_data)) {
                                throw new Exception('商品库存修改失败，请重试');
                            }
                        }
                    }
                }

                // 重置用户优惠券
                $reward = DB::table('user_reward')->where('order_id',$order->id)->first();
                if(!empty($reward)){
                    $reward_data['repay_time'] = 0;
                    $reward_data['repay_account'] = 0;
                    $reward_data['order_id'] = 0;
                    if(!DB::table('user_reward')->where('id',$reward->id)->update($reward_data)){
                        throw new Exception('优惠券返还失败，请重试');
                    }
                    $reward_activity = DB::table('activity_sale')->where('id',$reward->activity_sale_id)->first();
                    if($reward_activity){
                        if($reward_activity->amount_use > 0){
                            $reward_activity_data['amount_use'] = $reward_activity->amount_use - 1;
                            if(!DB::table('activity_sale')->where('id',$reward_activity->id)->update($reward_activity_data)){
                                throw new Exception('优惠券返还失败，请重试');
                            }
                        }
                    }
                }
                // 满减使用数量-1
                $act_id = $order->activity_id;
                if($act_id > 0){
                    $activity = DB::table('activity_sale')->where('id',$act_id)->first();
                    if($activity){
                        if($activity->amount_use > 0){
                            $activity_data['amount_use'] = $activity->amount_use - 1;
                            if(!DB::table('activity_sale')->where('id',$activity->id)->update($activity_data)){
                                throw new Exception('满减活动返还失败，请重试');
                            }
                        }
                    }
                }
                // 如果是八贝币支付，需要移除冻结的八贝币
                if($order->pay_type == 3){
                    // 如果是八贝币支付，请求接口
                    if ($order->pay_type == 3) {
                        $user = DB::table('user')->where('id',$order->user_id)->first();
                        $this->box_service = new DreamBoxService();
                        $res = $this->box_service->coin_cancel($user->openid,$order->online_order); // 通知取消八贝币订单
                        if($res != 1){
                            throw new Exception($res);
                        }
                    }
                }
            }


            DB::commit();
            Redis::del($lock_key);
            Cache::forget('user:info_' . $order->user_id);
            Log::channel('overtime_order')->info('执行成功：【'.$order->online_order.'】');
        }catch(Exception $e){
            DB::rollBack();
            Log::channel('overtime_order')->info('执行错误：【'.$order->online_order.'】'.$e->getMessage());
        }
    }

    /**
     * 获取锁
     * @param  String  $key    锁标识
     * @param  Int     $expire 锁过期时间
     * @return Boolean
     */
    public function lock($key, $expire = 5) {
        $is_lock = Redis::setnx($key, time() + $expire);
        // 不能获取锁
        if (!$is_lock) {
            // 判断锁是否过期
            $lock_time = Redis::get($key);
            // 锁已过期，删除锁，重新获取
            if (time() > $lock_time) {
                Redis::del($key);
                $is_lock = Redis::setnx($key, time() + $expire);
            }
        }

        return $is_lock ? true : false;
    }
}
